/**************************************************
               fpc/fpp/fpp3.c
written by IL
edited by CAS

contains main()
**************************************************/
#define MAIN
#include "fpshr.h"
#include "fpstruct.h"
#include "gex.h"
#include <malloc.h>
#include <pwd.h>

#include <ctype.h>
#include "../seq/seq.h"

extern int Zbatch_flag;
extern void Zbatch(); /* see clam/batch.c */
void freelistmem(void);
struct contig *clhigh = NULL; /* pointer to the highlighted clone */
int highmark=-1;
int highremark=-1;  /*fred 4/22/03*/
int highseq = 0;

int showburied = 1; /* flag used to see if buried clones are displayed */

float ZOOM = 1.0; /* initialise zoom's to 1 and shifts to 0 */
float zoomfactor = 2.0;
float NEWZOOM = 1.0;
float YSHIFT = 0.0;
float FPZOOM = 1.0;
float FPYSHIFT = 0;

int currentctg = -1;
int currentclone = -1;
float scale,fpheight;
int centre_pos = INT_MIN;
int minx = -500;
int lastbox = 0 ;
float sizepercol;

/* sness */
int autosave_stats = 0;

#ifdef MYDEBUG
 BOOL scrcoor = FALSE;
 BOOL info = FALSE;
 BOOL fmap = FALSE;
 BOOL regionflag = FALSE; 
 BOOL where = TRUE;
#endif
 float MAP_POS_X = 0.0;
 int gelmax = 0;
 int band = 0,botscrollbox = 0,gelscrollbar = 0,gelcolstart=0;
 int scaleband = 0,keysetband=0,maxpage=0,upkey=0,downkey=0;
 int MAP_BOX = 0;
 int fpcolstart = 0;
 BOOL fpmove = FALSE;
 BOOL deletefp = FALSE;
 BOOL fpflag = FALSE;
 BOOL displaybars = FALSE;
 BOOL markerReset = FALSE;
 BOOL update = FALSE;     /* used to see if data has changed and wether to save before exiting */
 Graph g7 = 0; /* clone information */
 Graph g2 = 0; /* list of contigs */
 Graph g3 = 0; /* finger print maps */
 Graph g4 = 0; /* mode (stop) display */
 Graph g5 = 0; /* addclone display */
 Graph gconfig = 0; /* configure (global) display) */
 Graph gmessage = 0; /* message display */
 Graph gtest=0 , gtrace=0 ;
 Graph gtextwhole = 0; /* all of project displayed as text */
 Graph gmarker = 0;
 Graph gsequence = 0;
 Graph gselected = 0;
 Graph gselected2 = 0;
 Graph gsearch = 0;
 Graph gcomment = 0;
 Graph gpace = 0;
 Graph gsubmit = 0;
/*  Last edited: Jan 16 14:43 1996 (il) */
 float endpoints[MAXLEVEL][MAXCOL]; /* number of (sub colomns)levels, number of colomns allowed */

 int colnum = 8,vertconbox = 20,hozconbox=20;
 float colwidth = COLWIDTH;
 char charmaxcol = 10;
 char reqctg[7];

 REGION region[REGNUM];      /* can have up to 4 region's defined */
 int regdef = 0;            /* index for region */
 int regtop = 0,regbot = 0;     /* box numbers for region bar's */
 int bar1 = 0,bar2 = 0 ;

int cloneindex[FPMAX]; /* clone index */
int clonefpindex[FPMAX]; /* clone's fp number index */
int indexbox[FPMAX]; /* box for clone's fp */

int gelclonebox[GELMAX],gelnamebox[GELMAX],gelhigh=-1;

Array clonepos = 0;

BOOL newctg = TRUE;
BOOL newsettings = FALSE;
BOOL preserve = FALSE;
int HIGHLIGHT = CYAN;
int FRIEND = DARKGREEN;
int SELECTED = LIGHTBLUE;
int PCRCOLOUR = YELLOW;
int BPYCOLOUR = LIGHTBLUE;
int MRKCOLOUR = YELLOW;
int lastctg = 0;

int page = 0; /* page number of ctg display 0 bieing the first */
int ctgmax = 0;

struct contig *root = NULL;

int fphigh=-1,tolerbox=0,fpcolourbox=0;
BOOL toler=TRUE,fpcolour= FALSE;
int nYAC = 5;
float yacwidth = 2.0;
int anchorMiniContig = 0;
int nProbe = 3 ;
int nREM = 7;
BOOL displaymap = TRUE;
int classctg = -1;
int main_classctg = -1;
BOOL  dataloaded = FALSE;
Graph gstart = 0;
char projectname[80],chsearchglob[NAME_SZ],commentglob[COMMENT_SZ],rmcommentglob[COMMENT_SZ];
char chaddname[10]="",chfpname[10]="";
float hozheight = 0.0;
int clonedisplayed = -1;
struct list *listroot = NULL;
FPC_SEQ* seqdisplayed = 0;

int gelclone[GELMAX],gelcount=0,gelcloneindex[GELMAX];
/* sness */
int gel_trail[GELMAX];
int geladdbox=0,fpflagbox=0;
BOOL geladd=FALSE;

int Nmarkers = 0;
BOOL minicontig = TRUE;
int lastpicked = -1,lastdbclicked = -1;
TEXTHIGH texthigh;
int displaycloneindex=0;
int currentmarker = -1;
struct markerdisplist *topmarkerlist = NULL, *popupmarkerlist = NULL;
BOOL merging = FALSE;
BOOL trail = FALSE;
BOOL barhighlighted = FALSE,fpadd = FALSE,zoominput = FALSE;
int reqbox = 0,zoombox=0,bar_active = 0,fpmovebox=0,fpremovebox = 0,fpaddbox = 0;
char reqzoom[5];
BOOL togglejustchanged = FALSE;
int trailbut = 0;
int editmenustatus = 0;
BOOL markeraddactive = FALSE,markerdelactive = FALSE,firstread =TRUE;
/* edit stuff */

struct marker tempmarker;
MARKEREDITLIST *rootmarkerptr = NULL;
struct markerctgpos *temppos = NULL;
struct remark *tempremark = NULL,*editremarkptr=NULL;
struct remark *tempremarkfp=NULL;
CLONE clone2;
int contigbox=0,lasteditbox=1,xbox=0,ybox=0;
char chctg[5],chx[5],chy[5];
char chctgmark[4],chpos[4];
int active =0,lastremarkpicked=-1;
Graph gmarkeredit1 = 0,gmarkeredit2=0,gcloneedit=0,gdispmarkers=0,gmarkerpopup=0;
EDIT *start=NULL;
BOOL newmarker = FALSE;
int editmarkerstatus = 0,editmarker = -1, editclonestatus = 0;
int parentbox = -1;
char chparent[12];
int offset = 0;
/* end edit stuff */
struct preslist *preservelist=NULL;

int  mergecontig1=0,mergecontig2=0,startpt=0;
BOOL fpcreadflag = FALSE;
BOOL okaytowrite,writeaccess=FALSE;
int searchtype =1;
char timestamp[255];
int addbox =0;
BOOL PRTMOVE = TRUE;
int defaultflag;
int alloc_contig =350;
float boxstart =0.0;
char reqclone[CLONE_SZ];
char req2ctg[30];
BOOL movedone = FALSE;

BOOL debug = FALSE;
int num_of_bands = 0;
int markerdisplayed =-1;

extern char helpfilepath[];

BOOL fppInsert_NoSort(Array a, char *s, int *index, BOOL (*order)());
BOOL fppFind_NoSort(Array a, char *s, int *ip, BOOL (* order)(void*, void*));
extern struct hash_list_element* clone_hash_table[HASH_SIZE];
unsigned int hash_clone(char* name);
void add_to_hash(unsigned int hash, int i);
extern void init_window_ptrs();
extern void batch_help();

/*****************************************************************
                     main()
*****************************************************************/
#ifndef OMIT_MAIN
int main(int argc, char **argv)
{
void fpquit(), gelquit(), fpc_unlockit();
  struct passwd *uinfo;

  init_window_ptrs();  /* WN 04/04 */
  init_seq_tree();

  sprintf(helpfilepath," ");

  texthigh.project = texthigh.markers = 0;
  texthigh.ctg = texthigh.clonebox = 0;
  texthigh.markerbox2 = 0;
  strcpy(chsearchglob,"");
  uinfo = (struct passwd *) getpwuid((uid_t) geteuid());
  if (uinfo == NULL)
    strcpy(commentglob,"&");
  else
    strcpy(commentglob,uinfo->pw_name);
  strcpy(rmcommentglob,"");

  if (argc > 1 && strcmp(argv[1], "-batch")==0) {
      batch_help();
  }
  
  if (argc > 2 && strcmp(argv[2], "-batch")==0) {
      strcpy(chsearchglob,"*"); /* CAS 11/1/98 to surppres messages */
      Zbatch(argc,argv);
      exit(0);
  }

  /*  g_thread_init(NULL); */
  graphInit(&argc,argv);               /*initialise the graph package */
  gexInit(&argc,argv);

  /*efriedr 8/15/01  This call is needed to make the gel images work. */
  graphSetInstallMap (TRUE);

  fpquit();                /* initializes fp stuff */
  gelquit();               /* initializes gel stuff */
  message_box(argc, argv);  /* brings up main menu */

  if(dataloaded){
    if(writeaccess)
      fpc_unlockit();
  }
  printf("Exiting FPC\n");
  return 0;
}
#endif

#define freeuper(x) (FREE_UPPER[x & 0xff])

int lexstrcmp_fpc(a,b)
char *a, *b;
{ char c,d,*p,*q;

  while (*a)
    {                /* Bond7 should come before Bond68 */
      if (isdigit((int)*a) && isdigit((int)*b))
        {
          for (p = a ; isdigit((int)*p) ; ++p) ;
          for (q = b ; isdigit((int)*q) ; ++q) ;
          if (p-a > q-b) { return 1 ; }  /* the longer number is the bigger */
          if (p-a < q-b) { return -1 ; }
          while (isdigit ((int)*a))
            { if (*a > *b) { return 1 ; }
              if (*a++ < *b++) { return -1 ; }
            }
        }
      else
        { if((c=freeuper(*a++))>(d=freeuper(*b++))) { return 1 ; }
          if(c<d) { return -1 ; }
        }
    }
  if (!*b) return 0;
  return -1;
}
typedef struct markerpos {
  struct marker *marker;
} MARKINDEX;



/*  BOOL markerOrder(char *s, MARKER *b) */
/*  { */
/*    return lexstrcmp(s, b->marker); */
/*  } */

/*  BOOL cloneOrder(char *s, CLONE *b) */
/*  { */
/*    return lexstrcmp(s, b->clone); */
/*  } */

BOOL markerOrder(void *s, void *b)
{
  return lexstrcmp_fpc((char*)s, ((MARKER*)b)->marker);
}

BOOL cloneOrder(void *s, void *b)
{
  return lexstrcmp_fpc((char*)s, ((CLONE*)b)->clone);
}

/***********************************************/
       /* Finds Entry s from Array  a
        * sorted in ascending order of order()
        * If found, returns TRUE and sets *ip
        * if not, returns FALSE and sets *ip one step left
        */

/*BOOL fppFind(Array a, char *s, int *ip, int (* order)(void*, void*)) */

/* WMN If this function returns false, it still sets ip to
    the best-matching clone. DO NOT change this behavior, which is used in 
    BSS */

BOOL fppFind(Array a, char *s, int *ip, BOOL (* order)(void*, void*))
{
int i, j, k, rc;

  i = 0 ; 
  j = arrayMax(a) -1;

  if(j== -1)
  { *ip = -1; 
    return FALSE;
  }  

  /* sness */
  /*  rc = order(s,uArray(a,j)); last element  */
  rc = order(s,uArray_dbg(a,j,__FILE__,__LINE__)); /* last element */
  if (rc == 0) 
  { *ip = j;
     return TRUE;
  }
  else if (rc > 0) 
  { *ip = j;
     return FALSE;
  }

  /* sness */
  /*  rc = order(s,uArray(a,0)); first element */
  rc = order(s,uArray_dbg(a,0,__FILE__,__LINE__)); /* first element */
  if (rc == 0) /* first element */
  { *ip = 0;
     return TRUE;
  }
  else if (rc < 0) 
  { *ip = -1;
     return FALSE;
  }
  while(TRUE)
    { k = i + ((j-i) >> 1) ; /* midpoint */
	/* sness */
    /*  rc = order(s,uArray(a,k)); */
    rc = order(s,uArray_dbg(a,k,__FILE__,__LINE__));
      if (rc == 0)
	{ 
	  *ip = k; 
	  return TRUE;
	}
      else if (rc > 0) i = k;
      else j = k;
      if (i == (j-1) )
        break;
    }
  *ip = i ;
  return FALSE;
}

/***********************************************/
       /* Finds Entry s from Array  a, using the existing hash table
        * If found, returns TRUE and sets *ip
        * if not, returns FALSE and sets *ip one beyond the end
        */

BOOL fppFind_NoSort(Array a, char *s, int *ip, BOOL (* order)(void*, void*))
{
    int i, rc;
    unsigned int hash;
    struct hash_list_element *next;

    hash = hash_clone(s);
    next = clone_hash_table[hash];
    while (next)
    {
        i = next->i;
        rc = order(s,arrp(acedata, i, CLONE)->clone);
        if (rc == 0)
        {
            *ip = i;
            return TRUE;
        }
        next = next->next;
    }
    /* if we got here then we did not find the clone, so point
        to one beyond the end of the existing array */
    *ip = arrayMax(a);
    add_to_hash(hash,*ip);
    return FALSE;
}

/*************************************************************
    W. Nelson 11/03
    This function doesn't actually insert anything. It looks
    for the given clone, and if not found, it ensures that the
    array is big enough to add one clone at the end.
**************************************************************/

BOOL fppInsert_NoSort(Array a, char *s, int *index, BOOL (*order)())
{

  if (fppFind_NoSort(a, s, index,order))
   return FALSE;  /* found it */

  uArray_dbg(a,arrayMax(a),__FILE__,__LINE__) ; /* to create space */
      
  return TRUE;
}

/**************************************************************/
BOOL fppInsert(Array a, char *s, int *index, BOOL (*order)())
{
  int i, j, k;
  char *loc, *cp, *cq;

  if (fppFind(a, s, index,order))
    return FALSE;  /* no doubles */
  
  i = *index;
  *index += 1;
  j = arrayMax(a) + 1;
  /* sness */
  /*loc = uArray(a,j-1) ; to create space */
  loc = uArray_dbg(a,j-1,__FILE__,__LINE__) ; /* to create space */

  cp =  loc + a->size - 1;  
  cq = loc - 1;
  k = (j - i - 2)*(a->size);
  while(k--)
      *cp-- = *cq--;
    
  return TRUE;
}
